#include <bits/stdc++.h>
using namespace std;
const int NMAX = 30;
int G[NMAX][NMAX]; // 存储边信息
int bestx[NMAX];   // 最优值的割集
int n, e;          // 顶点数，边数
// 
// 结点
struct Node {
  int depth; // 当前层
  int cut;   // 割边数量
  int e;     // 剩余边的数量
  int *x; // 解向量01序列【x1,x2,……xn】其中xi=1表示点xi在割集，0表示不在割集

  Node(int d, int c, int ee) {
    x = new int[n + 1];
    depth = d;
    cut = c;
    e = ee;
  }  
  //  割边数大的先出队列
  bool operator<(const Node &node) const { return cut < node.cut; }
};

// 存储待解决的结点的优先队列
priority_queue<Node> q;

// 从父节node点，扩展子结点
void addNode(Node node, bool isLeft) {
  Node now(node.depth + 1, node.cut, node.e);
  copy(node.x, node.x + n + 1, now.x); // 复制解向量
  // 是左结点
  if (isLeft) {
    now.x[now.depth] = 1;        // 标记是割集元素
    for (int i = 1; i <= n; i++) // 统计割边的增量
      if (G[now.depth][i])
        if (now.x[i] == 0) // 如果当前顶点在割集中，但边的另一个顶点不在割集
        {
          now.cut += G[now.depth][i]; // 割边的数量增加
          now.e -= G[now.depth][i];   // 剩余边的数量减少
        } else
          now.cut -= G[now.depth][i]; // 否则割边数量减少
  }
  q.push(now); // 加入优先队列
}

int search() {
  // 初始化
  Node node(0, 0, e); //
  for (int i = 1; i <= n; i++)
    node.x[i] = 0;
  int best = 0;
  // 分支限界求解
  while (true) {
    if (node.depth == n) // 某次到达叶子节点，如果比当前最优解更优，更新
    {
      if (node.cut > best) {
        best = node.cut;
        copy(node.x, node.x + n + 1, bestx);
        // break;
      }
    } else // 没有到达叶子节点
    {
      addNode(node, true);          // 加入左子结点
      if (node.cut + node.e > best) // 满足约束条件，加入右子结点
        addNode(node, false);
    }

    if (q.empty())
      break;
    else // 取出队首元素
    {
      node = q.top();
      q.pop();
    }
  }
  return best;
}

int main() {
  ios::sync_with_stdio(false);
  // sync_with_stdio函数设置为false后可以解除这种同步，让std :: cin和std ::
  // cout不再经过缓冲区，iostream的性能就会提高了很多倍。因此，当解除同步之后，注意不要与scanf和printf混用以免出现问题。
  cin.tie(0);
  // 在默认的情况下cin绑定的是cout，每次执行 <<
  // 操作符的时候都要调用flush，这样会增加IO负担。可以通过tie(0)（0表示NULL）来解除cin与cout的绑定，进一步加快执行效率。

  cin >> n >> e;
  memset(G, 0, sizeof(G));
  for (int i = 1; i <= e; i++) {
    int a, b;
    cin >> a >> b;
    G[a][b]++;
    G[b][a] = G[a][b];
  }
  cout << search();

  /*
  cout << endl;
  for (int i = 1; i <= n; i++) {
    cout << bestx[i] << " ";
  }
  */

  return 0;
}

/*

测试数据：
7 18
1 4
1 5
1 6
1 7
2 3
2 4
2 5
2 6
2 7
3 4
3 5
3 6
3 7
4 5
4 6
5 6
5 7
6 7

结果：
12
1 1 1 0 1 0 0

*/